require "bit"

local bor = bit.bor
local band = bit.band
local lshift = bit.lshift
local rshift = bit.rshift

local table = {}

-- A bit string divided into 32-bit integers consisting of
-- the 24 bits 0x0000ff repeated.
for i=1,100 do
	table[3*i - 2] = 0xff0000ff
	table[3*i - 1] = 0x00ff0000 --16711680
	table[3*i    ] = 0x0000ff00 --65280
end

local in_bit_count = 32
local in_buf = 0
local n = 0

function get24bits()
	local read_before = in_bit_count
	local read_after = read_before + 24
	local v

	-- Moving this inside the true-body of the following 'if' also makes
	-- the code work correctly.
	local buf = in_buf

	if read_after <= 32 then
		in_bit_count = read_after

		-- Replacing 'buf' with 'in_buf' here makes the code
		-- work correctly.
		v = rshift(buf, read_before) 
	else
		v = rshift(rshift(in_buf, 1), read_before - 1)

		n = n + 1
		in_buf = table[n]

		v = bor(v, lshift(in_buf, 32 - read_before))

		in_bit_count = read_before - 8
	end

	return band(v, 0xffffff)
end

-- Putting the code in this function into the top-level
-- also makes the bug go away.
function bug_test()
	for i=1,100 do
		local r = get24bits()
		if r ~= 0x0000ff then
			-- This fails at the 60th iteration
			assert(false, "Expected 0x0000ff at " .. i .. " got " .. r)
		end
	end
end

bug_test()